<?php

namespace app\common\service;

use app\common\exception\BusinessException;
use app\common\helper\WxBizDataHelper;
use app\common\helper\WxHelper;
use app\common\model\AppConfig;

class WxService
{
    /**
     * appId
     * @var string
     */
    private $appId = '';

    /**
     * @param false|mixed|string $appId
     */
    public function setAppId($appId): WxService
    {
        $this->appId = $appId;
        return $this;
    }

    /**
     * getConfig
     * @return array
     * @throws BusinessException
     */
    private function getConfig(): array
    {
        // 查询配置信息
        $appConfigModel = new AppConfig();
        $config = $appConfigModel->getByIdAndType($this->appId, 'wx_mcp');
        if (!$config) {
            throw new BusinessException('此应用未配置微信小程序参数');
        }

        return $config;
    }

    /**
     * 获取小程序用户登录信息
     * @param string $code
     * @param string $iv
     * @param string $encryptedData
     * @return array
     * @throws BusinessException
     */
    public function getUserInfo(string $code, string $iv = '', string $encryptedData = ''): array
    {
        // 提取小程序配置
        $config = $this->getConfig();

        // code换openId/unionid/session_key
        $info = WxHelper::code2Session($config['appId'], $config['appSecret'], $code);
        if ($encryptedData && $iv) {
            $wxBiz = new WxBizDataHelper($config['appId'], $info['session_key']);
            $bizData = [];
            $bizCode = $wxBiz->decryptData($encryptedData, $iv, $bizData);
            if ($bizCode !== 0) {
                throw new BusinessException('微信解密服务异常:' . $bizCode);
            }
            $info = array_merge($info, $bizData);
        }

        //返回
        return $info;
    }

    /**
     * getUserInfoByCode
     * @param string $code
     * @return array
     * @throws BusinessException
     */
    public function getUserInfoByCode(string $code): array
    {
        // 提取小程序配置
        $config = $this->getConfig();

        //code换openId/unionid/session_key
        return WxHelper::code2Session($config['appId'], $config['appSecret'], $code);
    }

    /**
     * 获取小程序来源
     * @param string $code
     * @param string $iv
     * @param string $encryptedData
     * @return array
     * @throws BusinessException
     */
    public function decryptData(string $code, string $iv = '', string $encryptedData = ''): array
    {
        // 提取小程序配置
        $config = $this->getConfig();

        // code换openId/unionid/session_key
        $info = WxHelper::code2Session($config['appId'], $config['appSecret'], $code);
        if ($encryptedData && $iv) {
            $wxBiz = new WxBizDataHelper($config['appId'], $info['session_key']);
            $bizData = [];
            $bizCode = $wxBiz->decryptData($encryptedData, $iv, $bizData);
            if ($bizCode !== 0) {
                throw new BusinessException('微信解密服务异常:' . $bizCode);
            }
            $info = array_merge($info, $bizData);
        }

        //返回
        return $info;
    }

    /**
     * getUserPhoneNumber
     * @param $code
     * @return string
     * @throws BusinessException
     */
    public function getUserPhoneNumber($code): string
    {
        // 获取手机号码信息
        return WxHelper::getUserPhoneNumber($this->getAccessToken(), $code);
    }

    /**
     * sendCustomMessage
     * @param $message
     * @throws BusinessException
     */
    public function sendCustomMessage(array $message)
    {
        // 发送客服信息
        WxHelper::sendCustomMessage($this->getAccessToken(), $message);
    }

    /**
     * sendSubscribeMessage
     * @param $message
     * @throws BusinessException
     */
    public function sendSubscribeMessage(array $message)
    {
        // 发送订阅消息
        WxHelper::sendSubscribeMessage($this->getAccessToken(), $message);
    }

    /**
     * getAccessTokenData
     * @return array
     * @throws BusinessException
     */
    protected function getAccessTokenData()
    {
        // 提取小程序配置
        $config = $this->getConfig();

        // 获取accessToken
        return WxHelper::getAccessToken($config['appId'], $config['appSecret']);
    }

    /**
     * getAccessToken
     * @return string
     */
    public function getAccessToken(): string
    {
        $accessTokenData = $this->getAccessTokenData();
        return $accessTokenData['access_token'];
    }
}